#ifndef MASTER_H
#define MASTER_H

//#include <queue>
#include <string>
#include <list>
#include "server.h"
#include <pthread.h>
#include "load.pb.h"
#include "client_server.pb.h"
#include "structures.h"

using std::string;

class Slave {
	public:
		int aggregateLoad;	//TODO: Define some mapping from 3 load parameter
		// to int
		string ip;
		double idle_perc;
		double rps;
		double wps;

		Slave(const Load& sl, int aload) : aggregateLoad(aload) {
			ip = string(sl.ip());
			std::cout << " load ip in const " << ip;

			idle_perc  = sl.idle_perc();
			rps = sl.rps();
			wps = sl.wps();
		}
		Slave() {}
		bool friend operator<(const Slave &a, const Slave &b) {
			return (a.aggregateLoad > b.aggregateLoad) ? true : false;
		}
		string getIP(void) {
			std::cout << "getIP() : " << ip;
			return ip;
		}
		void increaseLoad(uint32_t);
		void updateLoad(const Load& s);
};

typedef std::list<Slave> slaveList;

class Master : public Server {

	pthread_mutex_t slaveListLock;	//To protect minHeap
	//priority_queue<Slave> minHeap;
	slaveList slaves;	//We keep this sorted according to aggregateLoad
	//TODO: A map for quick update/removal?

	Slave& getMinLoaded(bool &);
	string getMinIP(uint32_t reduce_size);
	void changeLoad(Load &s);
	void handleClient(Socket *sock);
	void handleSlave(Socket *sock);
	//TODO: Think of a formula for this
	int calculateLoad(const Load &s) {
		return (int) s.idle_perc();
	}

	public:
	Master(char* host, unsigned short port);
	~Master();
	void start(void);
	void HandleRequest(Socket *);
};

#endif
